#![no_std]

#[cfg(target_arch = "x86_64")]
extern crate test;

pub mod register;
#[macro_export]
macro_rules! csrr {
    ($reg:tt) => {
        {
            let id: usize;
            unsafe {
                core::arch::asm!(concat!("csrr {}, ", stringify!($reg)), out(reg)id);
            }
            id
        }
    };
}
#[macro_export]
macro_rules! csrr64 {
    ($reg:tt) => {
        {
            let id: u64;
            unsafe {
                core::arch::asm!(concat!("csrr {}, ", stringify!($reg)), out(reg)id);
            }
            id
        }
    };
}
/// 1. csr -> rd
/// 2. rs -> csr
#[macro_export]
macro_rules! csrrw {
    ($reg:tt, $rs:expr) => {
        {
            let rd:usize;
            unsafe {
                core::arch::asm!(concat!("csrrw {}, ", stringify!($reg), ",{}"), out(reg)rd, in(reg)$rs);
            }
            rd
        }
    };
}
#[macro_export]
macro_rules! csrw {
    ($reg:tt, $val:expr) => {
        {
            unsafe {
                core::arch::asm!(concat!("csrw ", stringify!($reg), ", {}"), in(reg)$val);
            }
        }
    };
}
/// 将 csr 寄存器中的低 5 bit 中的任意 bit 位置 1。
/// csrsi(reg, mask), 相当于 reg = reg | mask。
/// i 表示立即数，所以不存在其他寄存器的读写操作。
///
/// > mask 必须是一个字面量，在实际调用的时候可能并不怎么直观。
#[macro_export]
macro_rules! csrsi {
    ($reg:tt, $mask:literal) => {{
        unsafe {
            core::arch::asm!(concat!("csrsi ", stringify!($reg), ",", stringify!($mask)));
        }
    }};
}
#[macro_export]
macro_rules! csrci {
    ($reg:tt, $mask:literal) => {{
        unsafe {
            core::arch::asm!(concat!("csrci ", stringify!($reg), ",", stringify!($mask)));
        }
    }};
}
#[macro_export]
macro_rules! csrs {
    ($reg:tt, $mask:expr) => {{
        unsafe {
            core::arch::asm!(concat!("csrs ", stringify!($reg), ",", "{}"), in(reg)$mask);
        }
    }};
}
#[macro_export]
macro_rules! csrc {
    ($reg:tt, $mask:expr) => {{
        unsafe {
            core::arch::asm!(concat!("csrc ", stringify!($reg), ",", "{}"), in(reg)$mask);
        }
    }};
}
#[macro_export]
macro_rules! mask {
    ($start:literal ..= $end:literal) => {
        (((1 << $end) - (1 << $start)) | (1 << $end))
    };
    ($start:literal) => {
        (1 << start)
    };
}

pub enum PrivilegeLevel {
    User,
    Supervisor,
    Machine,
    Reserved(usize),
}

impl From<usize> for PrivilegeLevel {
    fn from(value: usize) -> Self {
        match value {
            0 => PrivilegeLevel::User,
            1 => PrivilegeLevel::Supervisor,
            3 => PrivilegeLevel::Machine,
            _ => PrivilegeLevel::Reserved(value),
        }
    }
}
impl Into<usize> for PrivilegeLevel {
    fn into(self) -> usize {
        match self {
            PrivilegeLevel::User => 0,
            PrivilegeLevel::Supervisor => 1,
            PrivilegeLevel::Machine => 3,
            PrivilegeLevel::Reserved(x) => x,
        }
    }
}
pub mod exception;
pub mod interrupt;
